home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / WLIB.ZIP / WTIME.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  15.7 KB  |  759 lines

  1. #include <time.h>
  2. #include <ctype.h>
  3. #include <WTime.h>
  4. #include <WDOS.h>
  5. #include <WBits.h>
  6. #pragma hdrstop
  7.  
  8. // copyright (c) 1993 by Paul Wheaton
  9.  
  10. extern int DOM[12];//={31,28,31,30,31,30,31,31,30,31,30,31};
  11.  
  12. //.parse
  13.  
  14. /*
  15.  
  16. Converting Julian to Gregorian dates and back.  According to the Gregorian
  17. Calendar Principle:
  18.  
  19.           Each year has 365 days in it
  20.           EXCEPT years that are evenly divisible by 4    (366 days)
  21.           EXCEPT years that are evenly divisible by 100  (365 days)
  22.           EXCEPT years that are evenly divisible by 400  (366 days)
  23.  
  24. Most four year chunks (a quad) are 1461 days.
  25. Most 100 year chunks (a century) are 36,524 days.
  26. All 400 year chunks (quad century) are 116,877 days.
  27. In theory, the first year (Year 0000) was a leap year.
  28.  
  29. If you wanted to, you could assume that there are 365.2425 days in the
  30. average year.  If you do try this, remember that floating point math can
  31. throw you a little bit of round off error - add 0.0000000001 to everything.
  32.  
  33. I prefer to use integer math since I feel I have more control and more speed.
  34.  
  35. The way I calculate it, all Quads will have four years where the first year
  36. is 366 days and each one after that is 365 days.  EXCEPT for a Quad that is the
  37. first Quad in a Century
  38.  
  39. */
  40.  
  41. Bool LeapYear(int Year)
  42.   {
  43.     if ((Year%400)==0) return True;
  44.     if ((Year%100)==0) return False;
  45.     if ((Year%4)==0) return True;
  46.     return False;
  47.   }
  48.  
  49. static const long Q=1461L;    // number of days in four years (quad)
  50. static const long C=36524L;   // century
  51. static const long QC=146097L; // four centuries.
  52. int DOM[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  53.   // days of the month
  54.  
  55. static void ConvertJulianToGregorian(long J, int& Y, int& M, int& D)
  56.   {
  57.     long NumQC=J/QC;
  58.     Y=int(NumQC)*400;
  59.     J-=(QC*NumQC);
  60.     long NumC=0;
  61.     if (J>(C+1))
  62.       {
  63.         J-=(C+1);
  64.         Y+=100;
  65.         NumC=J/C;
  66.         Y+=int(NumC)*100;
  67.         J-=NumC*C;
  68.         NumC++;
  69.       }
  70.     if ((NumC>0)&&(J>(Q-1)))
  71.       {
  72.         J-=(Q-1);
  73.         Y+=4;
  74.       }
  75.     long NumQ=J/Q;
  76.     Y+=int(NumQ)*4;
  77.     J-=NumQ*Q;
  78.     int Jul=int(J);  // no more need for long int math
  79.     if (LeapYear(Y))
  80.       {
  81.         if (Jul>=366)
  82.           {
  83.             Jul-=366;
  84.             Y++;
  85.           }
  86.         else if (Jul==59) // Jan 1, would have Jul = 0, Feb 29 would have Jul=59
  87.           {
  88.             M=2;
  89.             D=29;
  90.             return;
  91.           }
  92.         else if (Jul>59) Jul--;
  93.       }
  94.     while (Jul>=365)
  95.       {
  96.         Jul-=365;
  97.         Y++;
  98.       }
  99.     M=0;
  100.     while(DOM[M]<=Jul)
  101.       {
  102.         Jul-=DOM[M];
  103.         M++;
  104.       }
  105.     M++;
  106.     D=Jul+1;
  107.   }
  108.  
  109. static long ConvertGregorianToJulian(int Y, int M, int D)
  110.   {
  111.     Bool Leap=LeapYear(Y-(Y%4));
  112.     int NumQC=Y/400;
  113.     Y-=NumQC*400;
  114.     long J=NumQC*QC;
  115.     int NumC=Y/100;
  116.     if (NumC>0)
  117.       {
  118.         Y-=NumC*100;
  119.         J+=(NumC*C)+1;  // the first century has one more day
  120.       }
  121.     int NumQ=Y/4;
  122.     Y-=NumQ*4;
  123.     if ((NumC!=0)&&(NumQ>0))
  124.       {
  125.         // generally, the first Q doesn't have a leap year
  126.         J+=1460;
  127.         NumQ--;
  128.       }
  129.     J+=NumQ*Q;
  130.     if (Leap)
  131.       {
  132.         if (Y>0)
  133.           {
  134.             J+=366;
  135.             Y--;
  136.           }
  137.         else if (M>2) J++;
  138.       }
  139.     while (Y>0)
  140.       {
  141.         J+=365;
  142.         Y--;
  143.       }
  144.     int I;
  145.     For(I,M-1) J+=DOM[I];
  146.     J+=(D-1);
  147.     return J;
  148.   }
  149.  
  150. Date::Date(const JulianDate& J)
  151.   {
  152.     ConvertJulianToGregorian(J.J,Y,M,D);
  153.   }
  154.  
  155. void Date::operator=(const JulianDate& J)
  156.   {
  157.     ConvertJulianToGregorian(J.J,Y,M,D);
  158.   }
  159.  
  160. Bool Date::operator==(const JulianDate& X) const
  161.   {
  162.     long J=ConvertGregorianToJulian(Y,M,D);
  163.     return (J==X.J);
  164.   }
  165.  
  166. Bool Date::operator<=(const JulianDate& X) const
  167.   {
  168.     long J=ConvertGregorianToJulian(Y,M,D);
  169.     return (J<=X.J);
  170.   }
  171.  
  172. Bool Date::operator>=(const JulianDate& X) const
  173.   {
  174.     long J=ConvertGregorianToJulian(Y,M,D);
  175.     return (J>=X.J);
  176.   }
  177.  
  178. Bool Date::operator!=(const JulianDate& X) const
  179.   {
  180.     long J=ConvertGregorianToJulian(Y,M,D);
  181.     return (J!=X.J);
  182.   }
  183.  
  184. Bool Date::operator<(const JulianDate& X) const
  185.   {
  186.     long J=ConvertGregorianToJulian(Y,M,D);
  187.     return (J<=X.J);
  188.   }
  189.  
  190. Bool Date::operator>(const JulianDate& X) const
  191.   {
  192.     long J=ConvertGregorianToJulian(Y,M,D);
  193.     return (J>=X.J);
  194.   }
  195.  
  196. JulianDate Date::operator+(long Days) const
  197.   {
  198.     JulianDate J(ConvertGregorianToJulian(Y,M,D)+Days);
  199.     return J;
  200.   }
  201.  
  202. JulianDate Date::operator-(long Days) const
  203.   {
  204.     JulianDate J(ConvertGregorianToJulian(Y,M,D)-Days);
  205.     return J;
  206.   }
  207.  
  208. long Date::operator-(const JulianDate& X) const
  209.   {
  210.     long J=ConvertGregorianToJulian(Y,M,D);
  211.     J-=X.J;
  212.     return J;
  213.   }
  214.  
  215. JulianDate Date::operator++(int)
  216.   {
  217.     JulianDate J(*this);
  218.     ConvertJulianToGregorian(J.J+1,Y,M,D);
  219.     return J;  // return the original value since this is a post inc
  220.   }
  221.  
  222. JulianDate Date::operator--(int)
  223.   {
  224.     JulianDate J(*this);
  225.     ConvertJulianToGregorian(J.J-1,Y,M,D);
  226.     return J;  // return the original value since this is a post dec
  227.   }
  228.  
  229. JulianDate Date::operator++()
  230.   {
  231.     JulianDate J(*this);
  232.     J.J++;
  233.     ConvertJulianToGregorian(J.J,Y,M,D);
  234.     return J;  // return the original value since this is a post inc
  235.   }
  236.  
  237. JulianDate Date::operator--()
  238.   {
  239.     JulianDate J(*this);
  240.     J.J--;
  241.     ConvertJulianToGregorian(J.J,Y,M,D);
  242.     return J;  // return the original value since this is a post dec
  243.   }
  244.  
  245. void Date::operator+=(long Days)
  246.   {
  247.     JulianDate J(*this);
  248.     J+=Days;
  249.     ConvertJulianToGregorian(J.J,Y,M,D);
  250.   }
  251.  
  252. void Date::operator-=(long Days)
  253.   {
  254.     JulianDate J(*this);
  255.     J-=Days;
  256.     ConvertJulianToGregorian(J.J,Y,M,D);
  257.   }
  258.  
  259. ////////////////////    Julian stuff
  260.  
  261. JulianDate::JulianDate(int Year, int Month, int Day)
  262.   {
  263.     J=ConvertGregorianToJulian(Year,Month,Day);
  264.   }
  265.  
  266. JulianDate::JulianDate(const Date& D)
  267.   {
  268.     J=ConvertGregorianToJulian(D.Y,D.M,D.D);
  269.   }
  270.  
  271. int JulianDate::Year() const
  272.   {
  273.     int Y,M,D;
  274.     ConvertJulianToGregorian(J,Y,M,D);
  275.     return Y;
  276.   }
  277.  
  278. int JulianDate::Month() const
  279.   {
  280.     int Y,M,D;
  281.     ConvertJulianToGregorian(J,Y,M,D);
  282.     return M;
  283.   }
  284.  
  285. int JulianDate::Day() const
  286.   {
  287.     int Y,M,D;
  288.     ConvertJulianToGregorian(J,Y,M,D);
  289.     return D;
  290.   }
  291.  
  292. void JulianDate::SetYear(int Year)
  293.   {
  294.     int Y,M,D;
  295.     ConvertJulianToGregorian(J,Y,M,D);
  296.     Y=Year;
  297.     J=ConvertGregorianToJulian(Y,M,D);
  298.   }
  299.  
  300. void JulianDate::SetMonth(int Month)
  301.   {
  302.     int Y,M,D;
  303.     ConvertJulianToGregorian(J,Y,M,D);
  304.     M=Month;
  305.     J=ConvertGregorianToJulian(Y,M,D);
  306.   }
  307.  
  308. void JulianDate::SetDay(int Day)
  309.   {
  310.     int Y,M,D;
  311.     ConvertJulianToGregorian(J,Y,M,D);
  312.     D=Day;
  313.     J=ConvertGregorianToJulian(Y,M,D);
  314.   }
  315.  
  316. void JulianDate::operator=(const Date& D)
  317.   {
  318.     J=ConvertGregorianToJulian(D.Y,D.M,D.D);
  319.   }
  320.  
  321. //.parse
  322.  
  323. String40 Date::DayStr() const
  324.   {
  325.     char* X="00";
  326.     X[0]=D/10+'0';
  327.     X[1]=D%10+'0';
  328.     return String40(X);
  329.   }
  330.  
  331. //.parse
  332.  
  333. String40 Date::MonthStr2() const
  334.   {
  335.     char* X="00";
  336.     X[0]=M/10+'0';
  337.     X[1]=M%10+'0';
  338.     return String40(X);
  339.   }
  340.  
  341. //.parse
  342.  
  343. Date::Date(const char* Text)
  344.   {
  345.     String40 S=Text;
  346.     /*  possible cases:
  347.            to                 Today
  348.            tom                Tomorrow
  349.            y                  Yesterday
  350.            m tu w th f sa su  (last) Mon, Tue, Wed, Thu, Fri, Sat, Sun
  351.  
  352.                 -30 (30 days ago)
  353.                 +30 (30 days from now)
  354.  
  355.                 01011993
  356.                 010193
  357.                 0101
  358.                 1-1-1993
  359.                 1-1-93
  360.                 1-1
  361.                 1/1/1993
  362.                 1/1/93
  363.                 1/1
  364.     */
  365.     S.Trim();
  366.     Y=0;
  367.     M=1;
  368.     D=1;
  369.     Date TD=Today();
  370.     JulianDate TDJ(TD);
  371.     int Pos;
  372.     while((Pos=S.Index('/'))!=NotFound) S[Pos]='-';
  373.     if (isdigit(S(0)))
  374.       {
  375.         if (S!="0")
  376.           {
  377.             if (!S.Find('-'))
  378.               {
  379.                 if ((S.Length()==8)||(S.Length()==6))
  380.                   {
  381.                     S.Insert('-',4);
  382.                     S.Insert('-',2);
  383.                   }
  384.                 else if (S.Length()==4) S.Insert('-',2);
  385.                 else S="";
  386.               }
  387.             if (S.Length()>2)
  388.               {
  389.                 int Pos=S.Index('-');
  390.                 M=atoi(S.Before(Pos));
  391.                 if (M<1) M=1;
  392.                 else if (M>12) M=12;
  393.                 S=S.After(Pos);
  394.                 Pos=S.Index('-');
  395.                 if (Pos==NotFound)
  396.                   {
  397.                     D=atoi(S);
  398.                     if (D<1) D=1;
  399.                     else if (D>31) D=31;
  400.                     Y=TD.Year();
  401.                     if ((*this)>TDJ) Y--;
  402.                   }
  403.                 else
  404.                   {
  405.                     D=atoi(S.Before(Pos));
  406.                     if (D<1) D=1;
  407.                     else if (D>31) D=31;
  408.                     Y=atoi(S.After(Pos));
  409.                     if (Y<100) Y+=1900;
  410.                   }
  411.                 if ((Y!=0)&&(D>28))
  412.                   {
  413.                     if (M==2)
  414.                       {
  415.                         if (LeapYear(Y)) D=29;
  416.                         else D=28;
  417.                       }
  418.                     else if (D>DOM[M-1]) D=DOM[M-1];
  419.                   }
  420.               }
  421.           }
  422.       }
  423.     else
  424.       {
  425.         if (S(0)=='-') (*this)=TDJ-(atoi(S.After(0)));
  426.         else if (S(0)=='+') (*this)=TDJ+(atoi(S.After(0)));
  427.         else
  428.           {
  429.             S.ToLower();
  430.             if (S.Before(3)=="tom") (*this)=TDJ+1;
  431.             else if (S.Before(2)=="to") (*this)=TDJ;
  432.             else if (S(0)=='y') (*this)=TDJ-1;
  433.             else
  434.               {
  435.                 int WD=7;
  436.                 if (S(0)=='m') WD=0;
  437.                 else if (S(0)=='w') WD=2;
  438.                 else if (S(0)=='f') WD=4;
  439.                 else if (S(0)=='t')
  440.                   {
  441.                     if (S(1)=='u') WD=1;
  442.                     else if (S(1)=='h') WD=3;
  443.                   }
  444.                 else if (S(0)=='s')
  445.                   {
  446.                     if (S(1)=='a') WD=5;
  447.                     else if (S(1)=='u') WD=6;
  448.                   }
  449.                 if (WD<7)
  450.                   {
  451.                     while(TDJ.DOW()!=WD) TDJ--;
  452.                     (*this)=TDJ;
  453.                   }
  454.               }
  455.           }
  456.       }
  457.   }
  458.  
  459. //.parse
  460.  
  461. const char* MonthName[13]=
  462.   {"","January","February","March","April","May","June","July","August",
  463.    "September","October","November","December"};
  464. const char* WeekdayName[7]=
  465.   {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
  466.  
  467. String40 Date::MonthStr() const
  468.   {
  469.     String40 MS=MonthName[M];
  470.     return MS;
  471.   }
  472.  
  473. String40 Date::DayName() const
  474.   {
  475.     String40 DN=WeekdayName[DOW()];
  476.     return DN;
  477.   }
  478.  
  479. String40 JulianDate::DayName() const
  480.   {
  481.     String40 DN=WeekdayName[DOW()];
  482.     return DN;
  483.   }
  484.  
  485. //.parse
  486.  
  487. int Date::DOW() const
  488.   {
  489.     return (JulianDate(*this).DOW());
  490.   }
  491.  
  492. //.parse
  493.  
  494. String40 Date::FullDesc() const
  495.   {
  496.     String40 S;
  497.     if (Y!=0) S=DayName()+", "+MonthStr()+' '+Str(D)+", "+Str(Y);
  498.     return S;
  499.   }
  500.  
  501. //.parse
  502.  
  503. String40 Date::ShortDesc() const
  504.   {
  505.     String40 S;
  506.     if (Y!=0) S=MonthStr2()+'-'+DayStr()+"-"+Str(Y);
  507.     return S;
  508.   }
  509.  
  510. //.parse
  511.  
  512. String40 Date::RelativePastStr() const
  513.   {
  514.     String40 S;
  515.     if (Y!=0)
  516.       {
  517.         JulianDate TJ(Today());
  518.         JulianDate J(*this);
  519.         if (J==TJ) S="Today";
  520.         else if (TJ-J==1) S="Yesterday";
  521.         else if (InRange(TJ-J,0L,6L)) S=J.DayName(); // "Monday", "Tuesday"...
  522.         else S=MonthStr()+' '+Str(D)+", "+Str(Y);
  523.       }
  524.     return S;
  525.   }
  526.  
  527. //.parse
  528.  
  529. String40 JulianDate::RelativePastStr(Bool Alpha) const
  530.   {
  531.     String40 S;
  532.     if (J!=0)
  533.       {
  534.         JulianDate TJ(Today());
  535.         if (TJ==J) S="Today";
  536.         else if (TJ-J==1) S="Yesterday";
  537.         else if (InRange((TJ-J).Val(),0L,6L)) S=DayName(); // "Monday", "Tuesday"...
  538.         else
  539.           {
  540.             Date D(*this);
  541.             if (Alpha) S=D.MonthStr()+' '+Str(D.Day())+", "+Str(D.Year());
  542.             else S=D.ShortDesc();
  543.           }
  544.       }
  545.     return S;
  546.   }
  547.  
  548. //.parse
  549.  
  550. static BitSet16 Month31;
  551. static Bool Month31Set=False;
  552.  
  553. Bool Date::Valid() const
  554.   {
  555.     if (!Month31Set) Month31=BitSet16(1,3,5,7,8,10,12);
  556.     if (Y>4000) return False;
  557.     if (Y<0) return False;
  558.     if (M<1) return False;
  559.     if (M>12) return False;
  560.     if (D<1) return False;
  561.     if (D>31) return False;
  562.     if (Month31(M)) return True;
  563.     if (D>30) return False;
  564.     if (M!=2) return True;
  565.     if (D<29) return True;
  566.     if (LeapYear(Y)) return True;
  567.     return False;
  568.   }
  569.  
  570. //.parse
  571.  
  572. JulianDate JulianDate::operator+(long Days) const
  573.   {
  574.     JulianDate JJ=*this;
  575.     JJ.J+=Days;
  576.     return JJ;
  577.   }
  578.  
  579. JulianDate JulianDate::operator-(long Days) const
  580.   {
  581.     JulianDate JJ=*this;
  582.     JJ.J-=Days;
  583.     return JJ;
  584.   }
  585.  
  586. JulianDate JulianDate::operator++(int) // postfix operator
  587.   {
  588.     JulianDate OJ(*this);
  589.     J++;
  590.     return OJ;
  591.   }
  592.  
  593. JulianDate JulianDate::operator--(int) // postfix operator
  594.   {
  595.     JulianDate OJ(*this);
  596.     J--;
  597.     return OJ;
  598.   }
  599.  
  600.  
  601. //.parse
  602.  
  603. Date Today()
  604.   {
  605.     Registers R;
  606.     R.AH()=0x2a;
  607.     CallBIOS(33,R);
  608.     Date D(R.CX(),R.DH(),R.DL());
  609.     return D;
  610.   }
  611.  
  612. /*
  613.  
  614.   Moment class.  Remember that there are 1440 minutes in a day.
  615.   No consideration is taken for GMT or daylight savings time.  If you
  616.   need that sort of stuff, you can inherit this class and do your own
  617.   tweaking.
  618.  
  619. */
  620.  
  621. //.parse
  622.  
  623. Moment::Moment(const JulianDate& J, int Hour, int Minute)
  624.   {
  625.     M=J.J*MinutesInADay+Hour*60+Minute;
  626.   }
  627.  
  628. //.parse
  629.  
  630. Time CurTime()
  631.   {
  632.     struct time t;
  633.     gettime(&t);
  634.     Time T(t.ti_hour,t.ti_min,t.ti_sec);
  635.     return T;
  636.   }
  637.  
  638. //.parse
  639.  
  640. int CurMinCount()
  641.   {
  642.     struct time t;
  643.     gettime(&t);
  644.     int X=t.ti_min+t.ti_hour*60;
  645.     return X;
  646.   }
  647.  
  648. //.parse
  649.  
  650. Moment CurMoment()
  651.   {
  652.     date d;
  653.     getdate(&d);
  654.     Moment M(JulianDate(d.da_year,d.da_mon,d.da_day));
  655.     M+=CurMinCount();
  656.     return M;
  657.   }
  658.  
  659. //.parse
  660.  
  661. String40 Time::ShortDesc()
  662.   {
  663.     String40 S;
  664.     if ((H==0)&&(M==0)) S="midnight";
  665.     else if ((H==12)&&(M==0)) S="noon";
  666.     else
  667.       {
  668.         int Hour=H;
  669.         Bool AM=(H<12);
  670.         if (!AM) Hour-=12;
  671.         if (Hour==0) Hour=12;
  672.         S+=Str(Hour)+':'+Form("@@",M)+(AM?"am":"pm");
  673.       }
  674.     return S;
  675.   }
  676.  
  677. //.parse
  678.  
  679. String40 Time::Desc()
  680.   {
  681.     String40 St;
  682.     if ((H==0)&&(M==0)) St="midnight";
  683.     else if ((H==12)&&(M==0)) St="noon";
  684.     else
  685.       {
  686.         int Hour=H;
  687.         Bool AM=(H<12);
  688.         if (!AM) Hour-=12;
  689.         if (Hour==0) Hour=12;
  690.         St+=Str(Hour)+':'+Form("@@",M)+':'+Form("@@",S)+(AM?"am":"pm");
  691.       }
  692.     return St;
  693.   }
  694.  
  695. //.parse
  696.  
  697. Time::Time(const Moment& MM)
  698.   {
  699.     int X=int(MM%MinutesInADay);
  700.     S=0;
  701.     M=X%60;
  702.     H=X/60;
  703.   }
  704.  
  705. //.parse
  706.  
  707. String40 Moment::RelativeDesc()
  708.   {
  709.     JulianDate J=*this;
  710.     Date D(J);
  711.     String40 S=D.RelativePastStr()+' ';
  712.     Time T(*this);
  713.     S+=T.ShortDesc();
  714.     return S;
  715.   }
  716.  
  717. //.parse
  718.  
  719. String40 Moment::FullDesc()
  720.   {
  721.     JulianDate J=*this;
  722.     Date D(J);
  723.     String40 S=D.FullDesc()+' ';
  724.     Time T(*this);
  725.     S+=T.ShortDesc();
  726.     return S;
  727.   }
  728.  
  729. //.parse
  730.  
  731. String40 Moment::ShortDesc()
  732.   {
  733.     JulianDate J=*this;
  734.     Date D(J);
  735.     String40 S=D.ShortDesc()+' ';
  736.     Time T(*this);
  737.     S+=T.ShortDesc();
  738.     return S;
  739.   }
  740.  
  741. //.parse
  742.  
  743. Moment Moment::operator-(long X)
  744.   {
  745.     Moment MM=M;
  746.     MM.M-=X;
  747.     return MM;
  748.   }
  749.  
  750. //.parse
  751.  
  752. Moment Moment::operator+(long X)
  753.   {
  754.     Moment MM=M;
  755.     MM.M+=X;
  756.     return MM;
  757.   }
  758.  
  759.